<script setup lang="ts">

import {ResourceContentApi, ResourceContentVO} from "@/api/resource/content";
import {ResourceGroupApi, ResourceGroupTreeVO} from "@/api/resource/group";
import {ResourceType} from "@/types/resource";
import {OrbitControls, useGLTF} from "@tresjs/cientos";
import {
  AmbientLight,
  Box3, DirectionalLight,
  Object3D,
  PerspectiveCamera,
  Scene,
  Vector3,
  WebGLRenderer
} from "three";
import {TresCanvas} from "@tresjs/core";

const message = useMessage()
const emit = defineEmits(['selected'])

const show = ref(false)
const loading = ref(false)

const treeList = ref<ResourceGroupTreeVO[]>([])
const contentList = ref<ResourceContentVO[]>([])
const imgList = ref<string[]>([])

// TODO 很奇怪，这里又变成了非数组？
const selectIds = ref<number>()
const selectId = computed(() => {
  // return selectIds.value?.at(-1)
  return selectIds.value
})
const selectContent = computed(() => contentList.value!.filter(content => content.groupId === selectId.value)!)

const cascaderProps = {
  value: 'id',
  label: 'name',
  children: 'groupChild',
  checkStrictly: true,
  emitPath: false,
}

/** 打开窗口 */
const open = () => {
  show.value = true

  if (!treeList.value?.length || !contentList.value?.length) {
    getList()
  }
}
defineExpose({open})

/** 关闭 */
const close = () => {
  currentModel.value = undefined
  currentImg.value = undefined
  showModel.value = false
  show.value = false
}

/** 获取数据 */
const getList = async () => {
  loading.value = true

  treeList.value = await ResourceGroupApi.getResourceGroupContentTreeList(ResourceType.MODEL)
  contentList.value = await ResourceContentApi.getResourceList(ResourceType.MODEL)

  imgList.value = await Promise.all(contentList.value.map((item) => loadModel(item.url)))

  loading.value = false
}

/** 加载模型 */
const loadModel = async (url: string) => {
  // 配置基础设施
  const scene = new Scene()
  const camera = new PerspectiveCamera()

  const renderer = new WebGLRenderer({
    antialias: true,
    preserveDrawingBuffer: true,
    alpha: true,
  })

  scene.background = null
  renderer.setSize(512, 512)

  try {
    // 加载模型
    const {scene: model} = await useGLTF(url, {draco: true})
    scene.add(model)

    // 设置相机位置
    const box = new Box3().setFromObject(model)
    const center = box.getCenter(new Vector3())
    const size = box.getSize(new Vector3()).length()

    camera.position.copy(center)
    camera.position.z += size * 1.5
    camera.lookAt(center)

    // 添加基础光照
    const ambientLight = new AmbientLight(0xffffff, 0.5);
    const directionalLight = new DirectionalLight(0xffffff, 0.8);
    directionalLight.position.set(5, 5, 5);
    scene.add(ambientLight, directionalLight);

    // 渲染单帧
    renderer.render(scene, camera)

    // 转成图片
    return renderer.domElement.toDataURL("image/png")
  } finally {
    // 清理资源
    scene.clear()
    renderer.dispose()
  }
}

/** 预览模型 **/
const dialogVisible = ref(false)
const dialogLoading = ref(false)
const model = shallowRef<Object3D | undefined>()
const previewModel = async () => {
  dialogVisible.value = true
  dialogLoading.value = true

  const {scene} = await useGLTF(currentModel.value!.url, {draco: true})
  model.value = scene

  dialogLoading.value = false
}

/** 点击图片 */
// 当前图片
const currentModel = ref<ResourceContentVO>()
const currentImg = ref<string>()
const showModel = ref(false)
const handleClick = (item: ResourceContentVO, index: number) => {
  currentModel.value = item
  currentImg.value = imgList.value[index]
}

// 选择图片
const handleSelect = async () => {
  try {
    await message.confirm('确定要选择该模型吗?', '选择模型', 'info')
    emit('selected', currentModel.value)
    close()
  } catch {}
}

</script>

<template>
  <Dialog
    v-model="show"
    title="选择图片"
    width="75%"
    :destroy-on-close="false"
  >
    <div v-loading="loading">
      <el-scrollbar max-height="600">
        <el-row :gutter="16">
          <el-col :span="20">
            <ContentWrap>
              <!--              <el-empty v-if="!selectIds?.length" description="暂无数据" />-->
              <el-empty v-if="!selectContent.length" description="暂无数据" />
              <el-row v-else :gutter="8">
                <el-col
                  v-for="(item, index) in selectContent"
                  :key="item.id"
                  :span="6"
                >
                  <el-card :body-style="{ padding: '4px' }" @click="handleClick(item, index)">
                    <el-image class="h-56 w-full" :src="imgList[index]" fit="fill">
                      <template #placeholder>
                        <div class="h-full w-full flex justify-center items-center">
                          <el-icon><Loading /></el-icon>
                        </div>
                      </template>
                    </el-image>
                    <el-space class="p-2" direction="vertical" alignment="normal">
                      <el-text size="large">{{ item.name }}</el-text>
                      <el-text type="info">{{ item.remark }}</el-text>
                    </el-space>
                  </el-card>
                </el-col>
              </el-row>
            </ContentWrap>
          </el-col>
          <el-col :span="4">
            <el-button
              class="w-full mb-4"
              v-loading="loading"
              type="primary"
              @click="getList"
            >
              刷新
            </el-button>
            <ContentWrap>
              <el-cascader
                class="w-full"
                v-model="selectIds"
                :options="treeList"
                :props="cascaderProps"
                placeholder="请选择分组"
                clearable
              />
            </ContentWrap>
            <ContentWrap v-if="currentModel">
              <el-image class="h-48 w-full" ref="currentImgRef" :src="currentImg" fit="fill">
                <template #placeholder>
                  <div class="h-full w-full flex justify-center items-center">
                    <el-icon><Loading /></el-icon>
                  </div>
                </template>
              </el-image>
              <el-space class="p-2" direction="vertical" alignment="normal">
                <el-text size="large">{{ currentModel.name }}</el-text>
                <el-text type="info">{{ currentModel.remark }}</el-text>
              </el-space>
            </ContentWrap>
            <ContentWrap v-if="currentModel">
              <el-button @click="previewModel">预览</el-button>
              <el-button type="primary" @click="handleSelect">选择</el-button>
            </ContentWrap>
          </el-col>
        </el-row>
      </el-scrollbar>
    </div>
  </Dialog>

  <Dialog v-model="dialogVisible" title="预览模型" width="800">
    <div style="height: auto; min-height: 600px" v-loading="dialogLoading">
      <TresCanvas>
        <TresPerspectiveCamera />
        <TresAmbientLight :intensity="1" />
        <OrbitControls make-default />

        <primitive v-if="!dialogLoading" :object="model" />
      </TresCanvas>
    </div>
  </Dialog>
</template>

<style scoped lang="scss">

</style>
